package Utility;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import Message.DateTime;
import Message.Base64;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
/**
 *
 * @author nguyendn
 */

@SuppressWarnings( "deprecation" )

public class CommonUtils {
    public static String getMD5(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] messageDigest = md.digest(input.getBytes());
            BigInteger number = new BigInteger(1, messageDigest);
            String hashtext = number.toString(16);
            while (hashtext.length() < 32) {
                hashtext = "0" + hashtext;
            }
            return hashtext;
        }
        catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }


    public static String getHashPassword(String str){
        byte[] x = str.getBytes();
        int[] blks = new int[(((x.length + 8) >> 6) + 1) * 16];
        int i;

        for(i = 0; i < x.length; i++) {
            //blks[i >> 2] |= x[i] << (24 - (i % 4) * 8);
            blks[i >> 2] |= (x[i] & 0xFF) << (24 - (i % 4) * 8);
        }

        blks[i >> 2] |= 0x80 << (24 - (i % 4) * 8);
        blks[blks.length - 1] = x.length * 8;

        // calculate 160 bit SHA1 hash of the sequence of blocks
        int[] w = new int[80];
        int a =  1732584193;
        int b = -271733879;
        int c = -1732584194;
        int d =  271733878;
        int e = -1009589776;

        for(i = 0; i < blks.length; i += 16) {
            int olda = a;
            int oldb = b;
            int oldc = c;
            int oldd = d;
            int olde = e;

            for(int j = 0; j < 80; j++) {
                w[j] = (j < 16) ? blks[i + j] : ( rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1) );
                int t = rol(a, 5) + e + w[j] + ( (j < 20) ?  1518500249 + ((b & c) | ((~b) & d))
                    : (j < 40) ?  1859775393 + (b ^ c ^ d)
                    : (j < 60) ? -1894007588 + ((b & c) | (b & d) | (c & d))
                    : -899497514 + (b ^ c ^ d) );
                e = d;
                d = c;
                c = rol(b, 30);
                b = a;
                a = t;
            }
            a = a + olda;
            b = b + oldb;
            c = c + oldc;
            d = d + oldd;
            e = e + olde;
        }

        // Convert 160 bit hash to base64
        int[] words = {a,b,c,d,e,0};
        byte[] base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes();
        byte[] result = new byte[28];
        for (i=0; i<27; i++) {
            int start=i*6;
            int word=start>>5;
            int offset=start & 0x1f;

            if (offset <= 26) {
                result[i] = base64[(words[word] >> (26 - offset)) & 0x3F];
            } else if (offset == 28) {
                result[i] = base64[(((words[word] & 0x0F) << 2) |
                                    ((words[word+1] >> 30) & 0x03)) & 0x3F];
            } else {
                result[i] = base64[(((words[word] & 0x03) << 4) |
                                    ((words[word+1] >> 28) & 0x0F)) & 0x3F];
            }
        }
        result[27]='=';
        return new String(result);
    }

    // Bitwise rotate a 32-bit number to the left
    private static final int rol(int num, int cnt) {
        return (num << cnt) | (num >>> (32 - cnt));
    }

    public static DateTime ParseSQLDate(java.sql.Date dt) {
        DateTime result;
        int year, month, day;

        // Core date format: (yyyy-mm-dd) --> 0123-56-89
        try {
            SimpleDateFormat sdfOutput = new SimpleDateFormat("dd/MM/yyyy");
//            log.info(sdfOutput.format(dt));
            String d = sdfOutput.format(dt);
            int i = d.indexOf("/");
            int j = d.lastIndexOf("/");

            day = Integer.parseInt(d.substring(0, i));
            month = Integer.parseInt(d.substring(i+1,j));
            year = Integer.parseInt(d.substring(j+1));

        } catch (Exception ex) {
            year = 0;
            month = 0;
            day = 0;
        }
        result = new DateTime(year,month,day,0,0,0,0);
        return result;
    }

    public static DateTime ParseCoreDate(String dt) {
        DateTime result;
        int year, month, day;

        // Core date format: (yyyy-mm-dd) --> 0123-56-89
        try {
            year = Integer.parseInt(dt.substring(0,4));
            month = Integer.parseInt(dt.substring(5,6));
            day = Integer.parseInt(dt.substring(8,9));
        } catch (Exception ex) {
            Date date = new Date();
            year = date.getYear();
            month = date.getMonth();
            day = date.getDay();
        }
        result = new DateTime(year,month,day,0,0,0,0);
        return result;
    }

    public static int ParseInt(String value) {
        int result = 0;
        try {
            result = Integer.parseInt(value,10);
        }
        catch (Exception ex) {
        }
        return result;
    }

    public static int getInt(Object obj) {
        int result = 0;
        if (obj!=null) result = (Integer) obj;
        return result;
    }

    public static ArrayList stringToArrayList(String list, String separator) {
        String[] pieces = list.split(separator);
        for (int i = pieces.length - 1; i >= 0; i--) {
            pieces[i] = pieces[i].trim();
        }
        return new ArrayList(Arrays.asList(pieces));
    }

    public static DateTime ParseSQLTimestamp(Timestamp ts) {
        int year, month, day, hour, minute, second;
        try {
            year = ts.getYear()+1900;
            month = ts.getMonth()+1;
            day = ts.getDate();
            hour = ts.getHours();
            minute = ts.getMinutes();
            second = ts.getSeconds();
        } catch (Exception ex) {
            Date date = new Date();
            year = date.getYear();
            month = date.getMonth();
            day = date.getDay();
            hour = date.getHours();
            minute = date.getMinutes();
            second = date.getSeconds();
        }
        DateTime result = new DateTime(year,month,day,hour,minute,second, 0);
        return result;
    }

    /**
     * Same as the normal <tt>in.read(b, off, len)</tt>, but
     *  tries to ensure that the entire len number of bytes
     *  is read.
     * <p>
     * If the end of file is reached before any bytes
     *  are read, returns -1.
     * If the end of the file is reached after some bytes are
     *  read, returns the number of bytes read.
     * If the end of the file isn't reached before len
     *  bytes have been read, will return len bytes.
     */
    public static int readFully(InputStream in, byte[] b, int off, int len) throws IOException
    {
        int total = 0;
        for (;;) {
            int got = in.read(b, off + total, len - total);
            if (got < 0) {
                return (total == 0) ? -1 : total;
            } else {
                total += got;
                if (total == len)
                    return total;
            }
        }
    }

    static Random generator = new Random();
    public static int random(int n) {
        return generator.nextInt(n);
    }
}
